#ifndef DESIGN_STATE_H_
#define DESIGN_STATE_H_

namespace state{

class GumballMachine;

class State
{
public:
    virtual void insertQuarter() = 0;
    virtual void ejectQuarter() = 0;
    virtual void turnCrank() = 0;
    virtual void dispense() = 0;
};

class NoQuarterState: public State
{
public:
    NoQuarterState(GumballMachine* g);
    virtual ~NoQuarterState(){}
public:
    virtual void insertQuarter();
    virtual void ejectQuarter();
    virtual void turnCrank();
    virtual void dispense();
private:
    GumballMachine* m_gMachine;
};

class HasQuarterState:public State
{
public:
    HasQuarterState(GumballMachine* g);
    virtual ~HasQuarterState(){}
public:
    virtual void insertQuarter();
    virtual void ejectQuarter();
    virtual void turnCrank();
    virtual void dispense();
private:
    GumballMachine* m_gMachine;
};

class SoldState:public State
{
public:
    SoldState(GumballMachine* g);
    virtual ~SoldState(){}
public:
    virtual void insertQuarter();
    virtual void ejectQuarter();
    virtual void turnCrank();
    virtual void dispense();
private:
    GumballMachine* m_gMachine;
};

class SoldOutState:public State
{
public:
    SoldOutState(GumballMachine* g);
    virtual ~SoldOutState(){}
public:
    virtual void insertQuarter();
    virtual void ejectQuarter();
    virtual void turnCrank();
    virtual void dispense();
private:
    GumballMachine* m_gMachine;
};

class GumballMachine
{
public:
    GumballMachine(int n);
public:
    void insertQuarter();
    void ejectQuarter();
    void turnCrank();

    void setState(State* s);
    void releaseBall();
    int   getCount();

    State* getNoQuarterState();
    State* getHasQuarterState();
    State* getSoldState();
    State* getSoldOutState();
private:
    int m_count;
    State* m_curState;
    State* m_noQuarter;
    State* m_hasQuarter;
    State* m_sold;
    State* m_soldOut;
};

}

#endif // DESIGN_STATE_H_
